import {
	isString,
	isPlainObject,
	forEach,
	assign,
	merge
} from './assist';
import store from '../store';

// 封装http服务
const defaults = {
	header: {
		'Content-Type': 'application/json'
	},
	timeout: 30000,
};

const statusText = {
	'0': '网络已断开！',
	'400': '错误的请求！',
	'401': '没有访问权限！',
	'403': '服务器拒绝访问！',
	'404': '请求的接口不存在！',
	'405': '禁用请求中指定的方法！',
	'408': '请求超时！',
	'500': '服务器内部错误！',
	'501': '无法识别请求！',
	'502': '错误网关！',
	'503': '服务不可用！',
	'504': '网关超时！',
	'505': 'HTTP协议版本不受支持！',
};

// 错误码 errCode
// "0000"  成功
// "0001"  未注册
// "0002"  已注册
// "2000"  用户已被注册
// "2001"  用户未注册
// "2997"  token已失效
// "2998"  业务处理失败
// "2999"  其他错误

function _execute(method, config) {
	// config.header['i'] = store.state.user.randomIv;
	if (config.baseUrl && !/^(http|ws)s?/.test(config.url)) {
		config.url = config.baseUrl + config.url;
	}

	return new Promise((resolve, reject) => {
		if (config.loadingText) {
			uni.showLoading({
				title: isString(config.loadingText) ? config.loadingText : '加载中',
				mask: true
			});
		}
		uni.showNavigationBarLoading();
		method(assign({}, config, {
			success: () => {
				config.loadingText &&
					uni.hideLoading(
					// {
					// 	complete: () => {
					// 		uni.showToast({
					// 			icon: 'success',
					// 			title: '加载完成',
					// 		})
					// 	}
					// }
					);
			},
			fail: () => {
				uni.hideLoading();
			},
			complete: (res) => {
				config.complete && config.complete(res);
				uni.hideNavigationBarLoading();

				if (res.header && res.header.i) {
					store.dispatch('setIv', res.header.i);
				}
				if (res.statusCode >= 200 && res.statusCode < 300) {
					return resolve(res);
				} else {
					let errMsg = res.errMsg;

					if (res.errMsg.indexOf('ok') > -1) {
						errMsg = statusText[res.statusCode] || '请求出错：' + (res.statusCode || '');
					}

					uni.showToast({
						icon: 'error',
						title: errMsg,
					});

					return reject(res);
				}
			},
		}));
	});
}

function http(instanceConfig) {
	this.config = instanceConfig || {};
}

http.prototype.request = function request(config) {
	config = merge({}, this.config, config);

	// 	if (config.header['Content-Type'] === 'application/json') {
	// 		config.data = JSON.stringify(config.data);
	// 	}

	return _execute(uni.request, config);
}

forEach(['get', 'post'], (method) => {
	http.prototype[method] = function(url, data, config) {
		return this.request(assign(config || {}, {
			method: method.toUpperCase(),
			url: url,
			data: data,
		}));
	};
});

forEach(['uploadFile', 'downloadFile', 'connectSocket'], (method) => {
	http.prototype[method] = function(config) {
		config = merge({}, this.config, config);

		if (config.baseUrl && !/^(http|ws)s?/.test(config.url)) {
			config.url = config.baseUrl + config.url;
		}

		if (method === 'connectSocket') {
			config.url = config.url.replace(/^http/, 'ws');
		} else {
			delete config.header['Content-Type'];
		}

		return uni[method](config);
	}
});

export default new http(defaults);